//***********************************************************************
// FileDescription:		interface for the CRSA class.
// FileVersion:			2006-09-09
// ProductVersion:		1, 0, 0, 1
//
// Portability:			ANSI C++
// Base Classes:		None.
// Support DLL:			HugeCalc.dll ( V6.0.0.2 or above )
// Related Document:	HugeCalc.chm
//
// Copyright (c) 2006 by Guo XianQiang. All right reserved.
//***********************************************************************

#if !defined(AFX_RSA_H__34130416_9155_483C_8291_ED09145ADA6F__INCLUDED_)
#define AFX_RSA_H__34130416_9155_483C_8291_ED09145ADA6F__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "../../../HugeCalc_API/CppAPI/Include/HugeCalc.h"
#include "../../../HugeCalc_API/CppAPI/Include/HugeIntX.h"

#define MINBITS				((UINT32)32)
#define MAXBITS				((UINT32)4096)
#define DEFAULTBITS			((UINT32)1024)

#define RSA_FASTTEST_STR	(_T("11"))
#define RSA_NORMALLY_STR	(_T("10001"))

typedef enum tagRSAParam
{
	RSA_E,
	RSA_P,
	RSA_Q,
	RSA_N,
	RSA_D,
	RSA_OM,
	RSA_EM,
	RSA_DM,
}RSAParam;

const BYTE BY_CHECK_E	= 0x01;	// E > 1 && E is an odd number? ( otherwise, Gcd(P-1, E) can't equal to 1 )
const BYTE BY_CHECK_PQ	= 0x02;	// P <> Q ?
const BYTE BY_CHECK_P	= 0x04;	// P is a prime ?
const BYTE BY_CHECK_Q	= 0x08;	// Q is a prime ?
const BYTE BY_CHECK_P_1	= 0x10;	// Gcd( P-1, E ) == 1 ?
const BYTE BY_CHECK_Q_1	= 0x20;	// Gcd( Q-1, E ) == 1 ?
const BYTE BY_CHECK_M	= 0x80;	// OM < N ?

const BYTE BY_PxQ_N		= 0x40;	// N is not from set
const BYTE BY_PQ_OK		= (BYTE)( ~( BY_CHECK_M | BY_PxQ_N ));
const BYTE BY_READY		= (BYTE)( ~BY_CHECK_M );

#define CHECK_FAIL_E(u)			( !( (u) & BY_CHECK_E ))
#define CHECK_FAIL_PQ(u)		( !( (u) & BY_CHECK_PQ ))
#define CHECK_FAIL_P(u)			( !( (u) & BY_CHECK_P ))
#define CHECK_FAIL_Q(u)			( !( (u) & BY_CHECK_Q ))
#define CHECK_FAIL_P_1(u)		( !( (u) & BY_CHECK_P_1 ))
#define CHECK_FAIL_Q_1(u)		( !( (u) & BY_CHECK_Q_1 ))
#define CHECK_FAIL_M(u)			( !( (u) & BY_CHECK_M ))

#define RSA_PQ_OK(u)			( BY_PQ_OK == ((u) & BY_PQ_OK ))
#define RSA_PxQ_N(u)			( BY_READY == ((u) & BY_PxQ_N ))
#define RSA_READY(u)			( BY_READY == ((u) & BY_READY ))

class CRSA
{
public:
	CRSA( void );
	/*virtual*/ ~CRSA();

	void SetHex( const BOOL bHex = TRUE );

	const BOOL GeneratePrime( UINT32 * const pKeyBits = NULL );

	const BYTE SetParam( const LPCTSTR lpszString, const RSAParam enumRSAParam = RSA_OM );
	const BYTE GetStatus( void ) const;

	const LPCTSTR GetParam( const RSAParam enumRSAParam = RSA_EM ) const;
	const UINT GetParamBits( const RSAParam enumRSAParam = RSA_N ) const;

	const LPCTSTR EncryptMessage( const LPCTSTR lpszText ) const;
	const LPCTSTR DecryptMessage( const LPCTSTR lpszHexNum ) const;

private:
	const BOOL CheckParam( const BYTE byCheckItem ) const;
	void GeneratePublicKey( void );
	void GeneratePrivateKey( void );

	CHugeIntX E;	// Encrypt Key E
	CHugeIntX P;	// 1st Prime P
	CHugeIntX Q;	// 2nd Prime Q
	CHugeIntX N;	// Public  Key N
	CHugeIntX D;	// Private Key D

	mutable CHugeIntX OM;	// Original Message
	mutable CHugeIntX EM;	// Encrypt Message
	mutable CHugeIntX DM;	// Decrypt Message

	mutable CHugeIntX PIQ;	// PIQ = P^(-1) mod P
	mutable CHugeIntX DP;	// DP = D mod ( P - 1 )
	mutable CHugeIntX DQ;	// DQ = D mod ( Q - 1 )

	mutable BYTE m_byStatus;
	mutable BOOL m_bHex;
};

#endif // !defined(AFX_RSA_H__34130416_9155_483C_8291_ED09145ADA6F__INCLUDED_)
